import org.junit.Test

import static junit.framework.Assert.assertFalse
import static junit.framework.Assert.assertEquals

/**
 * Created with IntelliJ IDEA.
 * User: vuntermann
 * Date: 21/05/13
 * Time: 18:29
 * To change this template use File | Settings | File Templates.
 */
class TicketTest {

    String PRODUCT_A = 'A'
    String PRODUCT_B = 'B'

    def PRICE_A_PER_UNIT = 50
    def PROMOTION_PRICE_A = 20
    def PROMOTION_COUNT_A = 2

    def PRICE_B_PER_UNIT = 100
    def PROMOTION_PRICE_B = 50

    @Test
    public void aNonExistentProductShouldBeAddedToTheTicketWithCountAsOne(){
        def ticket = new Ticket()

        ticket.add(PRODUCT_A)

        assertFalse ticket.ticketDetails.isEmpty()
        assertEquals 1, ticket.countOfProduct(PRODUCT_A)
    }

    @Test
    public void anExistentProductShouldIncreaseTheCountWhenIsAddedToTheTicket(){
        def ticket = new Ticket()

        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)

        assertFalse ticket.ticketDetails.isEmpty()
        assertEquals 2, ticket.countOfProduct(PRODUCT_A)
    }

    @Test
    public void calculateDiscountsForASingleProductWithPromotionComplete(){
        def promotions = ['A': new Promotion(2, PROMOTION_PRICE_A)]
        def priceList = ['A': PRICE_A_PER_UNIT]
        def ticket = new Ticket()

        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)

        ticket.calculateDiscounts(promotions, priceList)

        assertEquals(((2 * PRICE_A_PER_UNIT) - PROMOTION_PRICE_A) , ticket.ticketDetails[PRODUCT_A].productDiscount)
    }

    @Test
    public void calculateDiscountsForASingleProductWithOnePromotion(){
        def promotions = ['A': new Promotion(2, PROMOTION_PRICE_A)]
        def priceList = ['A': PRICE_A_PER_UNIT]
        def ticket = new Ticket()

        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)

        ticket.calculateDiscounts(promotions, priceList)

        assertEquals(((3* PRICE_A_PER_UNIT) - PROMOTION_PRICE_A) , ticket.ticketDetails[PRODUCT_A].productDiscount)
    }

    @Test
    public void calculateDiscountsForASingleProductWithMoreThanOnePromotionComplete(){
        def promotions = ['A': new Promotion(2, PROMOTION_PRICE_A)]
        def priceList = ['A': PRICE_A_PER_UNIT]
        def ticket = new Ticket()

        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)

        ticket.calculateDiscounts(promotions, priceList)

        def expectedDiscount =  PROMOTION_COUNT_A * ((4 * PRICE_A_PER_UNIT) - PROMOTION_PRICE_A)

        assertEquals(expectedDiscount, ticket.ticketDetails[PRODUCT_A].productDiscount)
    }

    @Test
    public void calculateDiscountsForASingleProductWithMoreThanOnePromotion(){
        def promotions = ['A': new Promotion(2, PROMOTION_PRICE_A)]
        def priceList = ['A': PRICE_A_PER_UNIT]
        def ticket = new Ticket()

        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)

        ticket.calculateDiscounts(promotions, priceList)

        def expectedDiscount = PROMOTION_COUNT_A * ((5 * PRICE_A_PER_UNIT) - PROMOTION_PRICE_A)

        assertEquals(expectedDiscount, ticket.ticketDetails[PRODUCT_A].productDiscount)
    }

    @Test
    public void calculateDiscountsForASingleProductWithoutPromotion(){
        def priceList = ['A': PRICE_A_PER_UNIT]
        def ticket = new Ticket()

        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)

        ticket.calculateDiscounts([:], priceList)

        assertEquals 0, ticket.ticketDetails[PRODUCT_A].productDiscount
    }

    @Test
    public void calculateTotalDiscountForProductsWithDiscount(){
        def promotions = ['A': new Promotion(2, PROMOTION_PRICE_A), 'B': new Promotion(2, PROMOTION_PRICE_B)]
        def priceList = ['A': PRICE_A_PER_UNIT, 'B': PRICE_B_PER_UNIT]
        def ticket = new Ticket()

        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_A)
        ticket.add(PRODUCT_B)
        ticket.add(PRODUCT_B)

        int totalDiscount = ticket.getTotalDiscount(promotions, priceList)

        int expectedTotalDiscount = ((2 * PRICE_A_PER_UNIT) - PROMOTION_PRICE_A) + ((2* PRICE_B_PER_UNIT) - PROMOTION_PRICE_B)

        assertEquals(expectedTotalDiscount , totalDiscount)
    }

}
